#ifndef __MY_UTIL__
#define __MY_UTIL__
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<sys/stat.h>
#include"bundle.h"
#include<experimental/filesystem>
#include<jsoncpp/json/json.h>


//自己的命名空间 云备份cloud
namespace cloud{
  namespace fs=std::experimental::filesystem;
  class FileUtil{
    private:
      std::string _filename;
    public:
      FileUtil(const std::string &filename):_filename(filename){};
      bool Remove(){
        if(this->Exists()==false)
          return false;
        remove(_filename.c_str());
        return true;
      }      
      //获取文件大小
      int64_t FileSize(){
          struct stat st;
          //文件名--路径，放入到st
          if(stat(_filename.c_str(),&st)<0)
          {
            std::cout<<"Get file size failed!"<<std::endl;
            return -1;
          }
          return st.st_size;
      }

      //获取最后一次更改时间
      time_t LastMTime(){
        struct stat st;
        if(stat(_filename.c_str(),&st)<0){
          std::cout<<"Get file size failed!"<<std::endl;
          return -1;
        }
        return st.st_mtime;
      }

      //获取最后一次访问时间
      time_t LastATime(){
        struct stat st;
        if(stat(_filename.c_str(),&st)<0){
          std::cout<<"Get file size failed!"<<std::endl;
          return -1;
        }
        return st.st_atime;
       }

      //获取文件名
      std::string FileName()
      {
        size_t pos=_filename.find_last_of("/");
        if(pos==std::string::npos) return _filename;

        return _filename.substr(pos+1);
      }

      bool GetPostLen(std::string*body,size_t pos,size_t len)//获取从this中pos开始共len长度字符串写入body中
      { 
        size_t fsize=this->FileSize();
        if(pos+len>fsize)
        {
          std:: cout<<"Get file len is error!\n";
          return false;
        }
        std::ifstream ifs;
        ifs.open(_filename,std::ios::binary);
        if(ifs.is_open()==false){
          std::cout<<"read:Open file failed!\n";
          return false;}
        ifs.seekg(pos,std::ios::beg);
        body->resize(len);
        ifs.read(&(*body)[0],len);
        if(ifs.good()==false)
        {
          std::cout<<"Get file content failed!\n";
          ifs.close();
          return false;
        }
        ifs.close();
        return true;
      }

      bool GetContent(std::string*body)
      {
        size_t fsize=this->FileSize();
        return GetPostLen(body,0,fsize);
      }

      bool SetContent(const std::string &body)
      {
        std::ofstream ofs;
        ofs.open(_filename,std::ios::binary);
        if(ofs.is_open()==false)
        {
          std::cout<<"write:Open file failed!\n";
          return false;
        }
        ofs.write(&body[0],body.size());
        if(ofs.good()==false)
        {
          std::cout<<"Write file content failed!\n";
          ofs.close();
          return false;
        }
        ofs.close();
        return true;
      }

      bool Compress(const std::string &filename)
      {
        //获取源文件数据
        std::string body;
        if(this->GetContent(&body)==false){
          std::cout<<"Compress get file content failed!\n";
          return false;
        }
        //对数据进行压缩
        std::string packed=bundle::pack(bundle::LZIP,body);
        //将压缩的数据放到压缩包中
        FileUtil fu(filename);
        if(fu.SetContent(packed)==false){
          std::cout<<"Compress write packed data failed\n";
          return false;
        }
         return true;
      }
      
      bool Uncompress(const::std::string &filename)
      {
        //获取压缩数据
        std::string body;
        if(this->GetContent(&body)==false){
          std::cout<<"Uncompress get content failed!\n";
          return false;
        }
        //进行解压缩
        std::string unpacked=bundle::unpack(body);
        //将解压缩数据放入文件中
        FileUtil fu(filename);
        if(fu.SetContent(unpacked)==false){
          std::cout<<"Uncompress write data failed\n";
          return false;
        }
        return true;
      }

      bool Exists(){
        return fs::exists(_filename);
      }

      bool CreateDirectory(){
        if(this->Exists()) return true;
        return fs::create_directories(_filename);
      }
//遍历目录下的文件，放入到arry中
      bool ScanDirectory(std::vector<std::string> *arry){
        for (auto& p: fs::directory_iterator(_filename)){
          if(fs::is_directory(p)==true) continue;
          arry->push_back(fs::path(p).relative_path().string());//relative_path带相对路径的文件名
        }
      }

};

class JsonUtil{
  public:
  static bool Serialize(const Json::Value &root,std::string *str){
  Json::StreamWriterBuilder swb;
  std::unique_ptr<Json::StreamWriter>sw(swb.newStreamWriter());
  std::stringstream ss;
  if(sw->write(root,&ss)!=0){
    std::cout<<"Json write failed!"<<std::endl;
    return false;
  }
  *str=ss.str();
  return true;
    }
  static bool UnSerialize(const std::string &str,Json::Value* root){
  Json::CharReaderBuilder crb;
  std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
  std::string err;
  bool ret=cr->parse(str.c_str(),str.c_str()+str.size(),root,&err);
  if(ret==false){
  std::cout<<"parse error:"<<err<<std::endl;
  return false;
  }
  return true;
  }
};
}
#endif
